home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Precision Software Appli…tions Silver Collection 1
/
Precision Software Applications Silver Collection Volume One (PSM) (1993).iso
/
windows
/
games
/
xlmath21.arj
/
SOURCE.ZIP
/
XLMDLG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-10
|
18KB
|
679 lines
/*----------------------------------------------------------------------*\
XLMDLG.C - Dialog Box functions
=========
Copyright 1992 by Roy Kari
Author: Roy Kari
Dept. of Chemistry
Laurentian University
Sudbury, Ont.
Canada P3E 2C6
(705) 675-1151
Internet: "ROY@NICKEL.LAURENTIAN.CA"
All dialog box procedures involve 4 distinct steps:
1. Prepare a textual range from the current selection and
use that range to prompt the user,
2. Get the user defined range and coerce the range to values,
3. Convert the values from XLOPER's to a floating point array and
call the custom function (see 2nd thoughts in XLMATH.C),
4. Receive the returned values from the custom function and put
these values into the Excel worksheet.
For an illustration, see the function CommDlg1()
\*----------------------------------------------------------------------*/
/* --------------------------< Include files >--------------------- */
#define WIN31
#define _MSC_VER 700
#include <windows.h>
#include <xlcall.h>
#include <framewrk.h>
#include "xlmath.h"
#include "xlutil.h"
/* -------< Forward dialog helper functions >--------------------- */
int PASCAL CommDlg1(LPXLOPER( FAR PASCAL __export *lpFn)(LPFP),
LPSTR *prgDlg, WORD rgDlgRows, WORD InRow, WORD OutRow);
int PASCAL CommDlg2(LPXLOPER( FAR PASCAL __export *lpFn)(LPFP,LPFP),
LPSTR *prgDlg, WORD rgDlgRows, WORD InRow1,
WORD InRow2, WORD OutRow);
LPFP PASCAL CopyXloperToFp(LPXLOPER pxArray);
LPFP PASCAL GetxlFpValues(LPXLOPER pxDialog, WORD wDlgRow);
int PASCAL SetValues(LPXLOPER pxValues);
//
// CopyXloperToxlFp() - copy values in xloper to fp structure
//
LPFP PASCAL CopyXloperToFp(LPXLOPER pxArray)
{
LPFP pfArray;
LPXLOPER pxSrc = pxArray->val.array.lparray;
WORD wRows = pxArray->val.array.rows;
WORD wCols = pxArray->val.array.columns;
WORD i, j, ij;
if (pxArray->xltype != xltypeMulti)
{
ErrorHandler(XLU_NO_ARRAY);
return NULL;
}
pfArray = GetMem( (sizeof(double)*wRows*wCols) +2*sizeof(WORD));
if (pfArray != NULL)
{
pfArray->wRows = wRows;
pfArray->wCols = wCols;
ij=0;
for (i=0; i<wRows; i++)
{
for (j=0; j<wCols; j++)
{
pfArray->Data[ij+j] = pxSrc->val.num;
pxSrc++;
}
ij += wCols;
}
}
return pfArray;
}
//
// SetValues() - xlSets values in range specified by dialog box
//
int PASCAL SetValues(LPXLOPER pxValues)
{
XLOPER xResult;
// strip xlbitDLLFree, will free internally
if ((pxValues->xltype & xlbitDLLFree) != 0)
{
pxValues->xltype = pxValues->xltype ^ xlbitDLLFree;
}
// gxOutRef previously created. Now make it a rectangular
// range from top-right & xlMulti rows and columns
// if error return, then use range previously defined
if (pxValues->xltype != xltypeErr)
{
RefSetRectangle(&gxOutRef, pxValues->val.array.rows,
(BYTE)pxValues->val.array.columns);
}
// if not overlapped set values
if (!IsReferencesOverlapped((LPXLOPER)&gxInRef, (LPXLOPER)&gxOutRef))
{
Excel(xlSet, &xResult, 2, (LPXLOPER)&gxOutRef, (LPXLOPER)pxValues);
}
// If NOT error return, then free the memory allocated
// to returned xloper array
if (pxValues->xltype != xltypeErr)
{
// free the memory & set NULL
xlAutoFree((LPVOID)pxValues);
}
return 1;
}
/*----------------------------------------------------------------------*\
Dialog Interface Functions
The convention is that a dialog box will invoke function
fXyz() which in turn will invoke Xyz() which finally invokes
_Xyz(). For example fSmoothWeight() which invokes SmoothWeight()
which invokes _SmoothWeight(). The following is an illustration.
fSmoothWeight() handles the dialog box,getting the user input and
the data. This function must be written by you and registered with
Excel as a custom command.
SmoothWeight() is the custom function which interfaces with the
library routine _SmoothWeight(). This function must also
be written by you and can usually be registered with Excel
as a custom function.
_SmoothWeight() is a C library function which actually does the work.
This function you can usually pick up from somewhere else such as
I did from Quinn-Curtis.
Easy, isn't it!
\*----------------------------------------------------------------------*/
int FAR PASCAL __export fDiagonalize(void)
{
return (CommDlg1(Diagonalize, &rgDlgDiag[0][0], (WORD)rgDlgDiagRows,
(WORD)DIAG_IN_ROW, (WORD)DIAG_OUT_ROW));
}
int FAR PASCAL __export fMODensity(void)
{
return (CommDlg2(MODensity, &rgDlgMO[0][0], (WORD)rgDlgMORows,
(WORD)MO_COEF_ROW, (WORD)MO_OCC_ROW, (WORD)MO_OUT_ROW));
}
int FAR PASCAL __export fCubicSplines(void)
{
return (CommDlg2(CubicSplines, &rgDlgSpline[0][0], rgSplineDlgRows,
SPLINE_XVAR_ROW, SPLINE_YVAR_ROW, SPLINE_OUT_ROW));
}
int FAR PASCAL __export fSmoothWt(void)
{
return(CommDlg2(SmoothWeights, &rgDlgWtSmooth[0][0], rgWtSmoothDlgRows,
WTSMOOTH_DATA_ROW, WTSMOOTH_WEIGHT_ROW, WTSMOOTH_OUT_ROW));
}
int FAR PASCAL __export fCustomFit(void)
{
return(CommDlg2(CustomFit, &rgDlgCustomFit[0][0], rgCustomFitDlgRows,
CFIT_DATA_ROW, CFIT_PARM_ROW, CFIT_OUT_ROW));
}
/*----------------------------------------------------------------------*\
Common Dialog Functions
In many cases, a dialog box will require one input and one
output range. This general case is implimented in the routine
CommDlg1() below. Other cases require two input ranges and one
output range. These are implimented in CommDlg2() below. In still
others, one requires a unique dialog box and those must be
implimented as unique dialog box functions, Ugh!
\*----------------------------------------------------------------------*/
//
// CommDlg1() - general function to display a dialog box with
// two range arguments; input & output range
//
int PASCAL CommDlg1(LPXLOPER(FAR PASCAL __export *lpFn)(LPFP),
LPSTR *prgDlg, WORD rgDlgRows,
WORD InRow, WORD OutRow)
{
int xlRet;
XLOPER xDialog;
XLOPER xDialogReturned;
XLOPER xIn, xOut, xValues;
LPXLOPER pxValueOut = NULL;
LPFP lpfpInput = NULL;
// STEP 1: prepare the dialog box
// get the SheetiD for the active sheet
if (!GetActiveSheetId())
{
// no active sheet; error emit in GetActiveSheet()
return 0;
}
// init the dialog xlMulti from definitions in header file
if (InitDialog( (LPXLOPER)&xDialog, prgDlg, rgDlgRows) == NULL)
{
return 0;
}
// get selection in text form
GetRefTextFromSelection((LPXLOPER)&xIn, (LPXLOPER)&xOut, 1);
// stuff into dialog box
SetInitialRange((LPXLOPER)&xIn, (LPXLOPER)&xDialog, InRow);
SetInitialRange((LPXLOPER)&xOut, (LPXLOPER)&xDialog, OutRow);
// show dialog box
xlRet =Excel(xlfDialogBox, (LPXLOPER)&xDialogReturned, 1, (LPXLOPER)&xDialog);
// STEP 2: coerce the values and copy them into a FP array
// free Excel str & xDialog
Excel(xlFree,0,1,(LPXLOPER)&xIn);
Excel(xlFree,0,1,(LPXLOPER)&xOut);
FreeMem((LPVOID)xDialog.val.array.lparray);
if (xlRet != xlretSuccess || xDialogReturned.xltype != xltypeMulti)
return 0;
// make global input ref based on dialog range
if (CreateGlobalRef((LPXLOPER)&gxInRef, (LPXLOPER)&xDialogReturned,
InRow))
{
// coerce to multi
Excel(xlCoerce, &xValues, 1, (LPXLOPER)&gxInRef);
// convert to floating point array
lpfpInput = CopyXloperToFp(&xValues);
Excel(xlFree, 0, 1, (LPXLOPER)&xValues);
if (lpfpInput)
{
// STEP 3: Call the custom function
// call the function which returns LPXLOPER
pxValueOut = (*lpFn)(lpfpInput);
FreeMem(lpfpInput);
// STEP 4: Set the returned values into the Excel sheet
// set the values
if (pxValueOut)
{
// create global output ref based on dialog
if (CreateGlobalRef((LPXLOPER)&gxOutRef,
(LPXLOPER)&xDialogReturned,OutRow))
{
// set the values to sheet & free memory
SetValues(pxValueOut);
}
}
}
}
Excel(xlFree, 0, 1, (LPXLOPER)&xDialogReturned);
return 1;
}
//
// CommDlg2() - general function to display a dialog box with
// three range arguments; input1, input2 & output range
//
int PASCAL CommDlg2(LPXLOPER( FAR PASCAL __export *lpFn)(LPFP,LPFP),
LPSTR *prgDlg, WORD rgDlgRows, WORD InRow1,
WORD InRow2, WORD OutRow)
{
int xlRet;
XLOPER xDialog;
XLOPER xDialogReturned;
XLOPER xIn1, xIn2, xOut, xTemp;
LPXLOPER pxValueOut = NULL;
LPFP lpfpArg1, lpfpArg2;
if (!GetActiveSheetId())
{
// no active sheet; error emit in GetActiveSheet()
return 0;
}
// init the dialog xlMulti
if (InitDialog( (LPXLOPER)&xDialog, prgDlg, rgDlgRows)==NULL)
{
return 0;
}
// get selection in text form for In1 & In2
GetRefTextFromSelection((LPXLOPER)&xIn1, (LPXLOPER)&xIn2, 1);
GetRefTextFromSelection((LPXLOPER)&xTemp, (LPXLOPER)&xOut, 2);
// stuff into dialog box
SetInitialRange((LPXLOPER)&xIn1, (LPXLOPER)&xDialog, InRow1);
SetInitialRange((LPXLOPER)&xIn2, (LPXLOPER)&xDialog, InRow2);
SetInitialRange((LPXLOPER)&xOut, (LPXLOPER)&xDialog, OutRow);
// show dialog box
xlRet =Excel(xlfDialogBox, (LPXLOPER)&xDialogReturned, 1, (LPXLOPER)&xDialog);
// free Excel str & xDialog
Excel(xlFree,0,1,(LPXLOPER)&xTemp);
Excel(xlFree,0,1,(LPXLOPER)&xIn1);
Excel(xlFree,0,1,(LPXLOPER)&xIn2);
Excel(xlFree,0,1,(LPXLOPER)&xOut);
FreeMem((LPVOID)xDialog.val.array.lparray);
if (xlRet != xlretSuccess || xDialogReturned.xltype != xltypeMulti)
return 0;
// get Arg1 & Arg2
if (CreateGlobalRef(&gxInRef, &xDialogReturned, InRow1))
{
Excel(xlCoerce, (LPXLOPER)&xTemp, 1, (LPXLOPER)&gxInRef);
lpfpArg1 = CopyXloperToFp(&xTemp);
Excel(xlFree, 0, 1, (LPXLOPER)&xTemp);
}
if (lpfpArg1 ==NULL)
{
goto abort;
}
if (CreateGlobalRef(&gxInRef, &xDialogReturned, InRow2))
{
Excel(xlCoerce, (LPXLOPER)&xTemp, 1, (LPXLOPER)&gxInRef);
lpfpArg2 = CopyXloperToFp(&xTemp);
Excel(xlFree, 0, 1, (LPXLOPER)&xTemp);
}
if (lpfpArg2 == NULL)
{
FreeMem(lpfpArg1);
goto abort;
}
// call the function
pxValueOut = (*lpFn)(lpfpArg1, lpfpArg2);
FreeMem(lpfpArg1);
FreeMem(lpfpArg2);
// set the values
if (pxValueOut)
{
if (CreateGlobalRef(&gxOutRef, &xDialogReturned, OutRow))
{
SetValues(pxValueOut);
}
}
abort:
Excel(xlFree, 0, 1, (LPXLOPER)&xDialogReturned);
return 1;
}
/*----------------------------------------------------------------------*\
Unique Dialog Boxes
\*----------------------------------------------------------------------*/
// fPolyCurveFit() - display dialog box for Polynolial curve fitting
//
int FAR PASCAL __export fPolyCurveFit(void)
{
int xlRet;
XLOPER xDialog;
XLOPER xDialogReturned;
XLOPER xXvar, xYvar, xOrder, xOut, xTemp;
LPXLOPER pxValueOut = NULL;
LPFP lpfpXvar = NULL;
LPFP lpfpYvar = NULL;
if (!GetActiveSheetId())
{
// no active sheet; error emit in GetActiveSheet()
return 0;
}
// init the dialog xlMulti
if (InitDialog( (LPXLOPER)&xDialog, &rgDlgPoly[0][0], rgPolyDlgRows)==NULL)
{
return 0;
}
// get selection in text form for Xvar & Yvar
GetRefTextFromSelection((LPXLOPER)&xXvar, (LPXLOPER)&xYvar, 1);
GetRefTextFromSelection((LPXLOPER)&xTemp, (LPXLOPER)&xOut, 2);
// stuff into dialog box
SetInitialRange((LPXLOPER)&xXvar, (LPXLOPER)&xDialog, POLY_XVAR_ROW);
SetInitialRange((LPXLOPER)&xYvar, (LPXLOPER)&xDialog, POLY_YVAR_ROW);
SetInitialRange((LPXLOPER)&xOut, (LPXLOPER)&xDialog, POLY_OUT_ROW);
// show dialog box
xlRet =Excel(xlfDialogBox, (LPXLOPER)&xDialogReturned, 1, (LPXLOPER)&xDialog);
// free Excel str & xDialog
Excel(xlFree,0,1,(LPXLOPER)&xTemp);
Excel(xlFree,0,1,(LPXLOPER)&xXvar);
Excel(xlFree,0,1,(LPXLOPER)&xYvar);
Excel(xlFree,0,1,(LPXLOPER)&xOut);
FreeMem((LPVOID)xDialog.val.array.lparray);
if (xlRet != xlretSuccess || xDialogReturned.xltype != xltypeMulti)
return 0;
// get Xvar & Yvar
if (CreateGlobalRef(&gxInRef, &xDialogReturned, POLY_XVAR_ROW))
{
Excel(xlCoerce, (LPXLOPER)&xTemp, 1, (LPXLOPER)&gxInRef);
lpfpXvar = CopyXloperToFp(&xTemp);
Excel(xlFree, 0, 1, (LPXLOPER)&xTemp);
}
if (lpfpXvar ==NULL)
goto abort;
if (CreateGlobalRef(&gxInRef, &xDialogReturned, POLY_YVAR_ROW))
{
Excel(xlCoerce, (LPXLOPER)&xTemp, 1, (LPXLOPER)&gxInRef);
lpfpYvar = CopyXloperToFp(&xTemp);
Excel(xlFree, 0, 1, (LPXLOPER)&xTemp);
}
if (lpfpYvar == NULL)
{
FreeMem(lpfpXvar);
goto abort;
}
// Get order
Excel(xlCoerce, (LPXLOPER)&xOrder, 2,
(LPXLOPER)&xDialogReturned.val.array.lparray[POLY_ORDER_ROW*7+6],
TempInt(xltypeInt));
if (xOrder.xltype == xltypeInt)
{
// call the function
CreateGlobalRef(&gxOutRef, &xDialogReturned, POLY_OUT_ROW);
pxValueOut = PolyCurveFit(lpfpXvar, lpfpYvar, xOrder.val.w);
}
else
{
ErrorHandler(XLD_BAD_DIALOG);
}
FreeMem(lpfpXvar);
FreeMem(lpfpYvar);
// set the values
if (pxValueOut)
{
if (CreateGlobalRef(&gxOutRef, &xDialogReturned, POLY_OUT_ROW))
{
SetValues(pxValueOut);
}
}
abort:
Excel(xlFree, 0, 1, (LPXLOPER)&xDialogReturned);
return 1;
}
//
// fSmoothSg() - display dialog box for SG smoothing
//
int FAR PASCAL __export fSmoothSg(void)
{
int xlRet;
XLOPER xDialog;
XLOPER xDialogReturned;
XLOPER xData,xSmoothNum, xDerivNum, xOut;
LPXLOPER pxValueOut = NULL;
LPFP lpfpData = NULL;
if (!GetActiveSheetId())
{
// no active sheet; error emit in GetActiveSheet()
return 0;
}
// init the dialog xlMulti
if (InitDialog( (LPXLOPER)&xDialog, &rgDlgSgSmooth[0][0], rgSgSmoothDlgRows)==NULL)
{
return 0;
}
// get selection in text form
GetRefTextFromSelection((LPXLOPER)&xData, (LPXLOPER)&xOut, 1);
// stuff into dialog box
SetInitialRange((LPXLOPER)&xData, (LPXLOPER)&xDialog, SGSMOOTH_DATA_ROW);
SetInitialRange((LPXLOPER)&xOut, (LPXLOPER)&xDialog, SGSMOOTH_OUT_ROW);
// show dialog box
xlRet =Excel(xlfDialogBox, (LPXLOPER)&xDialogReturned, 1, (LPXLOPER)&xDialog);
// free Excel str & xDialog
Excel(xlFree,0,1,(LPXLOPER)&xData);
Excel(xlFree,0,1,(LPXLOPER)&xOut);
FreeMem((LPVOID)xDialog.val.array.lparray);
if (xlRet != xlretSuccess || xDialogReturned.xltype != xltypeMulti)
return 0;
// get Data values
if (CreateGlobalRef(&gxInRef, &xDialogReturned, SGSMOOTH_DATA_ROW))
{
Excel(xlCoerce, (LPXLOPER)&xData, 1, (LPXLOPER)&gxInRef);
lpfpData = CopyXloperToFp(&xData);
Excel(xlFree, 0, 1, (LPXLOPER)&xData);
}
if (lpfpData)
{
// get SmoothNum & DerivNum
Excel(xlCoerce, (LPXLOPER)&xSmoothNum, 2,
(LPXLOPER)&xDialogReturned.val.array.lparray[SGSMOOTH_SMOOTHNUM_ROW*7+6],
TempInt(xltypeInt));
Excel(xlCoerce, (LPXLOPER)&xDerivNum, 2,
(LPXLOPER)&xDialogReturned.val.array.lparray[SGSMOOTH_DERIVNUM_ROW*7+6],
TempInt(xltypeInt));
// call the function
if ( (xSmoothNum.xltype == xltypeInt) &&
(xDerivNum.xltype == xltypeInt))
{
pxValueOut = SmoothSG(lpfpData, xSmoothNum.val.w, xDerivNum.val.w);
}
else
ErrorHandler(XLD_BAD_DIALOG);
FreeMem(lpfpData);
// set the values
if (pxValueOut)
{
if (CreateGlobalRef(&gxOutRef, &xDialogReturned, SGSMOOTH_OUT_ROW))
{
SetValues(pxValueOut);
}
}
}
Excel(xlFree, 0, 1, (LPXLOPER)&xDialogReturned);
return 1;
}
int FAR PASCAL __export fCalcSpline(void)
{
int xlRet;
XLOPER xDialog;
XLOPER xDialogReturned;
XLOPER xXorig, xCoef, xXcalc, xOut;
LPXLOPER pxValueOut = NULL;
LPFP lpfpXorig = NULL;
LPFP lpfpCoef = NULL;
LPFP lpfpXcalc = NULL;
if (!GetActiveSheetId())
{
// no active sheet; error emit in GetActiveSheet()
return 0;
}
// init the dialog xlMulti
if (InitDialog( (LPXLOPER)&xDialog, &rgDlgCalcSpline[0][0],
rgCalcSplineDlgRows)==NULL)
{
return 0;
}
// get selection in text form for Xorig & Coef
GetRefTextFromSelection((LPXLOPER)&xXorig, (LPXLOPER)&xCoef, 2);
GetRefTextFromSelection((LPXLOPER)&xXcalc, (LPXLOPER)&xOut, 6);
// stuff into dialog box
SetInitialRange((LPXLOPER)&xXorig, (LPXLOPER)&xDialog, CALCSPLINE_XORIG_ROW);
SetInitialRange((LPXLOPER)&xCoef, (LPXLOPER)&xDialog, CALCSPLINE_COEF_ROW);
SetInitialRange((LPXLOPER)&xXcalc, (LPXLOPER)&xDialog, CALCSPLINE_XCALC_ROW);
SetInitialRange((LPXLOPER)&xOut, (LPXLOPER)&xDialog, CALCSPLINE_OUT_ROW);
// show dialog box
xlRet =Excel(xlfDialogBox, (LPXLOPER)&xDialogReturned, 1, (LPXLOPER)&xDialog);
// free Excel str & xDialog
Excel(xlFree,0,1,(LPXLOPER)&xXcalc);
Excel(xlFree,0,1,(LPXLOPER)&xXorig);
Excel(xlFree,0,1,(LPXLOPER)&xCoef);
Excel(xlFree,0,1,(LPXLOPER)&xOut);
FreeMem((LPVOID)xDialog.val.array.lparray);
if (xlRet != xlretSuccess || xDialogReturned.xltype != xltypeMulti)
return 0;
// get Xorig
if (CreateGlobalRef(&gxInRef, &xDialogReturned, CALCSPLINE_XORIG_ROW))
{
Excel(xlCoerce, (LPXLOPER)&xXorig, 1, (LPXLOPER)&gxInRef);
lpfpXorig = CopyXloperToFp(&xXorig);
Excel(xlFree, 0, 1, (LPXLOPER)&xXorig);
}
if (lpfpXorig == NULL)
goto abort;
// get Coefs
if (CreateGlobalRef(&gxInRef, &xDialogReturned, CALCSPLINE_COEF_ROW))
{
Excel(xlCoerce, (LPXLOPER)&xCoef, 1, (LPXLOPER)&gxInRef);
lpfpCoef = CopyXloperToFp(&xCoef);
Excel(xlFree, 0, 1, (LPXLOPER)&xCoef);
}
if (lpfpCoef == NULL)
{
FreeMem(lpfpXorig);
goto abort;
}
// get Xcalc
if (CreateGlobalRef(&gxInRef,&xDialogReturned, CALCSPLINE_XCALC_ROW))
{
Excel(xlCoerce, (LPXLOPER)&xXcalc, 1, (LPXLOPER)&gxInRef);
lpfpXcalc = CopyXloperToFp(&xXcalc);
Excel(xlFree, 0, 1, (LPXLOPER)&xXcalc);
}
if (lpfpXcalc == NULL)
{
FreeMem(lpfpXorig);
FreeMem(lpfpCoef);
goto abort;
}
// call the function
pxValueOut = CalcSpline(lpfpXorig, lpfpCoef, lpfpXcalc);
FreeMem(lpfpXorig);
FreeMem(lpfpCoef);
FreeMem(lpfpXcalc);
// set the values
if (pxValueOut)
{
if( CreateGlobalRef(&gxOutRef, &xDialogReturned, CALCSPLINE_OUT_ROW))
{
SetValues(pxValueOut);
}
}
abort:
Excel(xlFree, 0, 1, (LPXLOPER)&xDialogReturned);
return 1;
}